#!/usr/bin/env python
# $Id: test2-56.py ddcad87fab9c 2013/08/17 19:20:30 pgurumur $
# Copyright (c) 2013 Prabhu Gurumurthy <pgurumur@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# File test2-56.py generated on Monday July 01, 2013 @16:35:28 PDT
#
__version__  = "$Revision: ddcad87fab9c $"
__author__   = "$Author: pgurumur $"
__modified__ = "$Date: 2013-08-17 19:20:30Z $"

import optparse
import os
import sys

from pyparsing import Suppress, quotedString, Group, Optional, Literal, Or
from pyparsing import LineEnd, pythonStyleComment, removeQuotes, oneOf
from pyparsing import ParseFatalException, ParseException, Keyword, Forward
from pyparsing import ZeroOrMore, Dict, StringEnd, Word, alphas, alphanums
from pyparsing import delimitedList, nums

from venya.lib import cmdparser, exception, ip, stdlib, sql
from venya.lib import dbmodel, model
from venya.tools import networkdb

class CommandError(Exception):
   pass

class commandparser(object):
   def __init__(self):
      super(commandparser, self).__init__()
      self._builtins = set()
      self._lb, self._rb = map(Suppress, "{}")
      self._lp, self._rp = map(Suppress, "()")
      self._lbk, self._rbk = map(Suppress, "[]")
      self._lt, self._gt = map(Suppress, "<>")
      self._quoted = quotedString.copy().setParseAction(
            removeQuotes)
      self._words = Or(Word(alphanums + "_-") + self._quoted)
      self._ipv4 = Word(nums + ".").setParseAction(self._checkip)
      self._ipv4Net = Word(nums + "." + "/").setParseAction(self._checkip)

   def kwadd(self, String = None, Issuppress = False):
      retval = None
      if String:
         self._builtins.add(String)
         if Issuppress:
            retval = Keyword(String).suppress()
         else:
            retval = Keyword(String)
      else:
         self.error("INTERNAL ERROR: no string given to add to keyword list!")

      return retval

   def iskw(self, string, suppress = False):
      retval = None
      if string in self._builtins:
         if suppress:
            retval = Keyword(string).suppress()
         else:
            retval = Keyword(string)

      return retval

   def _checkip(self, string, location, tokens):
      print(tokens)

   def _siteValidate(self, string, location, tokens):
      print(tokens)

   def _entityValidate(self, string, location, tokens):
      print(tokens)

   def _siteAction(self, string, location, tokens):
      print(tokens)

   def _entityAction(self, string, location, tokens):
      print(tokens)

   def _vlanAction(self, string, location, tokens):
      print(tokens)

   def _addressAction(self, string, location, tokens):
      print(tokens)

   def parse(self, stream):
      commands = oneOf(
            "add set update delete generate dump a ad se rem del up mod m dum")
      table = oneOf("all " + " ".join(networkdb.all_tables()))
      comment = Optional(oneOf("comments comment") + self._quoted)

      siteRule = Group(commands + table + self._words +
            Or(self.kwadd("addr") + self.kwadd("address")) + self._quoted +
            comment).setParseAction(self._siteAction)
      entityRule = Group(commands + table + self._words +
            Or(self.kwadd("use") + self.kwadd("in")) +
            (table + self._words).setParseAction(self._siteValidate) +
            comment).setParseAction(self._entityAction)

      address = Group(Or(
         self.iskw("addr") + self.iskw("address")) + self._ipv4Net + Optional(
            Or(self.kwadd("gateway") + self.kwadd("gw")) + self._ipv4) +
            comment)

      vlanRule = Group(commands + table + Word(nums) + Or(
         self.kwadd("n") + self.kwadd("name")) + self._words + Or(
            self.iskw("in") + self.iskw("use")) + (table + 
               self._words).setParseAction(self._entityValidate) + Optional(
                  Or(address + comment))).setParseAction(self._vlanAction)

      zoneRule

      rule = Forward()
      rule << ZeroOrMore(delimitedList(
         siteRule |
         entityRule |
         vlanRule)) + StringEnd()
      rule.ignore(Literal("\\") + LineEnd())
      rule.ignore(pythonStyleComment)

      results = None
      try:
         if os.path.exists(stream):
            with open(stream, "r") as fh:
               results = rule.parseString(fh.read())
         else:
            results = rule.parseString(stream)
      except ParseFatalException as err:
         raise CommandError(err)
      except ParseException as err:
         raise CommandError("syntax error on line %d, col %d" %(err.lineno,
            err.col))

class netops(cmdparser.GetOpt):
   option_list = (
         optparse.make_option("-d", "--database", type = "str",
            help = "Database file to use/create", dest = "database"),
         optparse.make_option("-c", "--config", type = "str",
            help = "Configuration file to use", dest = "config"),
   )

   help = """

   To be added
   """

   usage = "[ options ] [ commands ] command options"

   def __init__(self, **kwargs):
      super(netops, self).__init__(**kwargs)
      self._command = None

   def add(self):
      pass

   def get(self):
      pass

   def generate(self):
      pass

   def update(self):
      pass

   def remove(self):
      pass

   def dump(self):
      pass

   def fileparse(self):
      if len(self.arguments) != 3:
         self.error("%s: invalid number of arguments", str(self))

      parser = None
      try:
         parser = commandparser()
         parser.parse(self.arguments[-1])
      except CommandError as err:
         self.error("%s: %s", str(self), err)

   @cmdparser.getopts
   def handle(self):
      if len(self.arguments) > 1:
         command = self.arguments[1]
         if command in ('a', 'ad', 'add', 's', 'se', 'set'):
            self._command = "add"
            self.add()
         elif command in ('get'):
            self.get()
         elif command in ('gen', 'generate'):
            self._command = "generate"
            self.generate()
         elif command in ('u', 'up', 'update', 'mod', 'modify', 'm'):
            self._command = "update"
            self.update()
         elif command in ('r', 'rem', 'remove', 'del', 'delete'):
            self._command = "delete"
            self.remove()
         elif command in ('dum', 'dump'):
            self._command = "dump"
            self.dump()
         elif command in ('parse', 'p'):
            self.fileparse()

      try:
         handle = sql.sqlite(self.options.database)
         networkdb.create(handle.engine, handle.session)
      except sql.SQLError as err:
         self.error("%s: %s", str(self), str(err))

if __name__ == "__main__":
   """
   database = "network.db"

   handle = sql.sqlite(database)
   try:
      networkdb.create(handle.engine, handle.session)
   except sql.SQLError as err:
      raise ValueError(err)
   except networkdb.ModelError as err:
      raise ValueError(err)
   else:
      site1 = "BA1"
      site1addr = "2403 Walsh Ave, Santa Clara, CA 95051"
      site1comments = "Savvis SC5 datacenter"

      site2 = "BA2"
      site2addr = "1555 Plymouth St  Mountain View, CA 94043"
      site2comments = "Layer42 Mountain View datacenter"


      try:
         ba1site = networkdb.Site()
         retval = ba1site.save(name = site1, address = site1addr,
               comments = site1comments)
         print(retval)
      except networkdb.ModelError as err:
         print(err)

      try:
         ba2site = networkdb.Site(name = site2, address = site2addr,
               comments = site2comments)
         retval = ba2site.save()
         print(retval)
      except networkdb.ModelError as err:
         print(err)


      site = networkdb.Site(name = site1)
      entity = networkdb.Entity(name = "Production", site = site["pk"])
      retval = entity.save()
      entity = networkdb.Entity(name = "Production")
      # print(entity.get("name"))
      entity.update(comments = "Production entity rows, DEFGHI rows")
      # print(site["pk"], entity["pk"])
      # print(entity["comments"])

   else:
      # 10.8.64.0/24,,200,Rack I1,Notestore,
      # address = "10.8.64.0/24"
      # vlanid = 200
      # name = "BA1"
      address  = "2403 Walsh Ave, Santa Clara, CA 95051"
      comments = "Savvis SC5 datacenter"

      site = networkdb.Site()
      retval = site.save(name = name, address = address, comments = comments)
      print(retval)


      entity_name = "Production"
      site = site["pk"][0]
      comments = "Production space, all but A row"
      entity = networkdb.Entity(name = entity_name, site = site)
      entity.save()

      for ix in xrange(200, 210):
         print(ix)

      # description = "Rack I1, Notestore"

      # site = networkdb.Site(name = sitename)
      # print(site["pk"])

      # vlan = networkdb.Vlan()
      # vlan.save(name = "RACK_200", number = vlanid, site = sitename)

      # vlan = networkdb.Vlan()
      # vlan.save(name = "RACK_201", number = 201, site = sitename)
      # site.save(name = sitename, address = siteaddress,
            # comments = "Savvis SC5 datacenter")

      # ipblock.q = handle.session.query(ipblock.t)
      # print(ipblock.q)
      # print(dir(networkdb.Base))
      # print(dir(networkdb.Base.metadata))
      # tables = networkdb.Base.metadata.tables
      # for key, value in tables.items():
         # print(value.metadata)
         # print(key, value)

      # print(networkdb.Base.metadata.tables)
   """

   cmdline = None
   try:
      cmdline = netops(version = 0.1, args = sys.argv)
      if len(cmdline) <= 1:
         cmdline.printhelp()
      else:
         cmdline.handle()
   except exception.GetOptError as err:
      print(err)
      sys.exit(1)
